/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package com.gitee.kamismile.gateweb.component.server;


import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollChannelOption;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import com.gitee.kamismile.gateweb.component.handler.WebSocketServerInitializer;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public final class WebSocketServer {


    private Channel channel;

    @Autowired
    private WebSocketConstant webSocketConstant;

    @Autowired
    private WebSocketServerInitializer webSocketServerInitializer;

    public void start() throws Exception {


        String os = System.getProperty("os.name");


        EventLoopGroup bossGroup;
        EventLoopGroup workerGroup;

//        if (os.startsWith("win") || os.startsWith("Win")) {
//            bossGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors() * 10);
//            workerGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors() * 2);
//        } else {
//            bossGroup = new EpollEventLoopGroup(Runtime.getRuntime().availableProcessors() * 10);
//            workerGroup = new EpollEventLoopGroup(Runtime.getRuntime().availableProcessors() * 2);
//        }

        if (os.startsWith("win") || os.startsWith("Win")) {
            bossGroup = new NioEventLoopGroup(1, new DefaultThreadFactory("agent-boss", true));
            workerGroup = new NioEventLoopGroup(0, new DefaultThreadFactory("agent-worker", true));
        } else {
            bossGroup = new EpollEventLoopGroup(1, new DefaultThreadFactory("agent-boss", true));
            workerGroup = new EpollEventLoopGroup(0, new DefaultThreadFactory("agent-worker", true));
        }

        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup);
            if (os.startsWith("win") || os.startsWith("Win")) {
                b.channel(NioServerSocketChannel.class);
            } else {
                b.channel(EpollServerSocketChannel.class)
                        .option(EpollChannelOption.SO_REUSEPORT, true);
            }
            b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 120000)
                    .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                    .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                    .childOption(ChannelOption.TCP_NODELAY, true)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
            ;

            b.handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(webSocketServerInitializer);

            channel = b.bind(webSocketConstant.getInetHost(), webSocketConstant.getPort()).sync().channel();
            channel.closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }


}
